home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / games / nhak_src.zip / ENGRAVE.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  16KB  |  637 lines

  1. /*    SCCS Id: @(#)engrave.c    3.0    89/11/15
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include    "hack.h"
  6.  
  7. STATIC_VAR struct engr {
  8.     struct engr *nxt_engr;
  9.     char *engr_txt;
  10.     xchar engr_x, engr_y;
  11.     unsigned engr_lth;    /* for save & restore; not length of text */
  12.     long engr_time;    /* moment engraving was (will be) finished */
  13.     xchar engr_type;
  14. #define DUST    1
  15. #define ENGRAVE    2
  16. #define BURN    3
  17. #define MARK    4
  18. #define POLY    5    /* temporary type - for polymorphing engraving */
  19. } NEARDATA *head_engr;
  20.  
  21. STATIC_DCL void FDECL(del_engr, (struct engr *));
  22. STATIC_DCL struct engr * FDECL(engr_at,(XCHAR_P,XCHAR_P));
  23.  
  24. #ifdef OVLB
  25. /* random engravings */
  26. const char *random_engr[] =
  27.              {"Elbereth", "ad ae?ar um",
  28.              "?la? ?as he??",
  29.              /* more added by Eric Backus */
  30.              "?ilroy wa? h?re", "?ala??iel",
  31.              "Fo? a ?ood time c?ll 6?6-4311",
  32.              /* some other famous engravings -3. */
  33.              "Lasc?ate o?ni sp?ranz? o vo? c?'en?rate",
  34.              "Y?u won?t get i? up ?he ste?s",
  35.              "A.S. ->"};
  36.  
  37. #endif /* OVLB */
  38. #ifdef OVL0
  39.  
  40. STATIC_OVL struct engr *
  41. engr_at(x,y) register xchar x,y; {
  42. register struct engr *ep = head_engr;
  43.     while(ep) {
  44.         if(x == ep->engr_x && y == ep->engr_y)
  45.             return(ep);
  46.         ep = ep->nxt_engr;
  47.     }
  48.     return((struct engr *) 0);
  49. }
  50.  
  51. #ifdef ELBERETH
  52. int
  53. sengr_at(s,x,y)
  54.     register const char *s;
  55.     register xchar x,y;
  56. {
  57.     register struct engr *ep = engr_at(x,y);
  58.     register char *t;
  59.     register int n;
  60.  
  61.     if(ep && ep->engr_time <= moves) {
  62.         t = ep->engr_txt;
  63. /*
  64.         if(!strcmp(s,t)) return(1);
  65. */
  66.         n = strlen(s);
  67.         while(*t) {
  68.             if(!strncmp(s,t,n)) return(1);
  69.             t++;
  70.         }
  71.     }
  72.     return(0);
  73. }
  74. #endif
  75.  
  76. #endif /* OVL0 */
  77. #ifdef OVL2
  78.  
  79. void
  80. u_wipe_engr(cnt)
  81. register int cnt;
  82. {
  83.     if(!u.uswallow && !Levitation)
  84.         wipe_engr_at(u.ux, u.uy, cnt);
  85. }
  86.  
  87. #endif /* OVL2 */
  88. #ifdef OVL1
  89.  
  90. void
  91. wipe_engr_at(x,y,cnt) register xchar x,y,cnt; {
  92. register struct engr *ep = engr_at(x,y);
  93. register int lth,pos;
  94. char ch;
  95.     if(ep){
  96.         if(ep->engr_type != BURN) {
  97.         if(ep->engr_type != DUST) {
  98.             cnt = rn2(1 + 50/(cnt+1)) ? 0 : 1;
  99.         }
  100.         lth = strlen(ep->engr_txt);
  101.         if(lth && cnt > 0 ) {
  102.             while(cnt--) {
  103.                 pos = rn2(lth);
  104.                 if((ch = ep->engr_txt[pos]) == ' ')
  105.                     continue;
  106.                 ep->engr_txt[pos] = (ch != '?') ? '?' : ' ';
  107.             }
  108.         }
  109.         while(lth && ep->engr_txt[lth-1] == ' ')
  110.             ep->engr_txt[--lth] = 0;
  111.         while(ep->engr_txt[0] == ' ')
  112.             ep->engr_txt++;
  113.         if(!ep->engr_txt[0]) del_engr(ep);
  114.         }
  115.     }
  116. }
  117.  
  118. #endif /* OVL1 */
  119. #ifdef OVL2
  120.  
  121. void
  122. read_engr_at(x,y) register int x,y; {
  123. register struct engr *ep = engr_at(x,y);
  124. register int    canfeel;
  125.     if(ep && ep->engr_txt[0]) {
  126.         switch(ep->engr_type) {
  127.         case DUST:
  128.         if(!Blind) pline("Something is written here in the dust.");
  129.         canfeel = 0;
  130.         break;
  131.         case ENGRAVE:
  132.         pline("Something is engraved here on the floor.");
  133.         canfeel = 1;
  134.         break;
  135.         case BURN:
  136.         pline("Some text has been burned here in the floor.");
  137.         canfeel = 1;
  138.         break;
  139.         case MARK:
  140.         if(!Blind) pline("There's some graffiti here on the floor.");
  141.         canfeel = 0;
  142.         break;
  143.         default:
  144.         impossible("Something is written in a very strange way.");
  145.         canfeel = 1;
  146.         }
  147.         if (canfeel || !Blind)
  148.         You("%s: \"%s\".",
  149.               (Blind) ? "feel the words" : "read",  ep->engr_txt);
  150.     }
  151. }
  152.  
  153. #endif /* OVL2 */
  154. #ifdef OVLB
  155.  
  156. void
  157. make_engr_at(x,y,s)
  158. register int x,y;
  159. register const char *s;
  160. {
  161.     register struct engr *ep;
  162.  
  163.     if(ep = engr_at(x,y))
  164.         del_engr(ep);
  165.     ep = (struct engr *)
  166.         alloc((unsigned)(sizeof(struct engr) + strlen(s) + 1));
  167.     ep->nxt_engr = head_engr;
  168.     head_engr = ep;
  169.     ep->engr_x = x;
  170.     ep->engr_y = y;
  171.     ep->engr_txt = (char *)(ep + 1);
  172.     Strcpy(ep->engr_txt, s);
  173.     ep->engr_time = 0;
  174.     ep->engr_type = DUST;
  175.     ep->engr_lth = strlen(s) + 1;
  176. }
  177.  
  178. /*
  179.  *    freehand - returns true if player has a free hand
  180.  */
  181. int
  182. freehand(){
  183.     return(!uwep ||
  184.        !uwep->cursed ||
  185.        (uwep->olet != WEAPON_SYM && uwep->otyp != TIN_OPENER
  186.         && uwep->otyp != PICK_AXE && uwep->otyp != UNICORN_HORN) || 
  187.        (!bimanual(uwep) && (!uarms || !uarms->cursed)));
  188. /*    if ((uwep && bimanual(uwep)) ||
  189.         (uwep && uarms))
  190.         return(0);
  191.     else
  192.         return(1);*/
  193. }
  194.  
  195. static const char NEARDATA styluses[] = { '#', '-', TOOL_SYM, WEAPON_SYM, WAND_SYM, 0 };
  196. static const char NEARDATA too_large[] = { ARMOR_SYM, BALL_SYM, ROCK_SYM, 0 };
  197. static const char NEARDATA paper[] = { SCROLL_SYM,
  198. #ifdef SPELLS
  199.     SPBOOK_SYM,
  200. #endif
  201.     0 };
  202.  
  203. int
  204. doengrave(){
  205. register int len, tmp;
  206. register char *sp, *sptmp;
  207. register struct engr *ep, *oep = engr_at(u.ux,u.uy);
  208. char buf[BUFSZ];
  209. boolean jello = FALSE;
  210. xchar type, polytype = 0;
  211. int spct;        /* number of leading spaces */
  212. register struct obj *otmp;
  213.     multi = 0;
  214.  
  215.     if(u.uswallow) {
  216.         if (is_animal(u.ustuck->data)) {
  217.             pline("What would you write?  \"Jonah was here\"?");
  218.             return(0);
  219.         } else
  220.             if (is_whirly(u.ustuck->data)) {
  221.                 You("can't reach the ground.");
  222.                 return(0);
  223.             } else 
  224.                 jello = TRUE;
  225.     }
  226.  
  227.     /* one may write with finger, weapon or wand */
  228.     /* edited by GAN 10/20/86 so as not to change
  229.      * weapon wielded.
  230.      */
  231.     otmp = getobj(styluses, "write with");
  232.     if(!otmp) return(0);
  233.  
  234.     /* There's no reason you should be able to write with a wand
  235.      * while both your hands are tied up.
  236.      */
  237.     if (!freehand() && otmp != uwep && !otmp->owornmask) {
  238.         You("have no free %s to write with!", body_part(HAND));
  239.         return(0);
  240.     }
  241. #ifdef POLYSELF
  242.     if (cantwield(uasmon)) {
  243.         You("can't even hold anything!");
  244.         return(0);
  245.     }
  246. #endif
  247.     if(otmp == ublindf) {
  248.         pline("That is a bit difficult to engrave with, don't you think?");
  249.         return(1);
  250.     }
  251.     if(otmp != &zeroobj && index(too_large,otmp->olet)) {
  252.         You("can't engrave with such a large object!");
  253.         return(1);
  254.        }
  255.  
  256.     if (jello) {
  257.         You("tickle %s with your %s.", mon_nam(u.ustuck), 
  258.             (otmp == &zeroobj) ? makeplural(body_part(FINGER)) :
  259.             xname(otmp));
  260.         Your("message dissolves...");
  261.         return(0);
  262.     }
  263.  
  264.     if(otmp != &zeroobj && index(paper,otmp->olet)) {
  265.         Your("%s would get dirty.",xname(otmp));
  266.         return(1);
  267.     }
  268.  
  269.     if(Levitation && otmp->olet != WAND_SYM){        /* riv05!a3 */
  270.         You("can't reach the floor!");
  271.         return(0);
  272.     }
  273.  
  274.     if(otmp == &zeroobj) {
  275.         You("write in the dust with your %s.",
  276.             makeplural(body_part(FINGER)));
  277.         type = DUST;
  278.     } else if(otmp->olet == WAND_SYM && zappable(otmp)) {
  279.         /* changed so any wand gets zapped out */
  280.         if((objects[otmp->otyp].bits & NODIR))  {
  281.             zapnodir(otmp);
  282.             type = DUST;
  283.         }  else  {
  284.             switch(otmp->otyp)  {
  285.             case WAN_LIGHTNING:
  286.                 if(!objects[otmp->otyp].oc_name_known) {
  287.                     if(flags.verbose)
  288.                     pline("The %s is a wand of lightning!",
  289.                         xname(otmp));
  290.                     makeknown(otmp->otyp);
  291.                     more_experienced(0,10);
  292.                 }
  293.                 type = BURN;
  294.                 break;
  295.             case WAN_FIRE:
  296.                 if(!objects[otmp->otyp].oc_name_known) {
  297.                     if(flags.verbose)
  298.                     pline("The %s is a wand of fire!",
  299.                        xname(otmp));
  300.                     makeknown(otmp->otyp);
  301.                     more_experienced(0,10);
  302.                 }
  303.                 type = BURN;
  304.                 break;
  305.             case WAN_DIGGING:
  306.                 if(!objects[otmp->otyp].oc_name_known) {
  307.                     if(flags.verbose)
  308.                     pline("The %s is a wand of digging!",
  309.                        xname(otmp));
  310.                     makeknown(otmp->otyp);
  311.                     more_experienced(0,10);
  312.                 }
  313.                 type = ENGRAVE;
  314.                 break;
  315.             case WAN_POLYMORPH:
  316.                 if(oep)  {
  317.                     del_engr(oep);
  318.                     oep = 0;
  319.                     type = POLY;
  320.                 }  else
  321.                     type = DUST;
  322.                 break;
  323.             case WAN_COLD:
  324.                 type = DUST;
  325.                 if(!oep || (oep->engr_type != BURN))
  326.                     break;
  327.             case WAN_CANCELLATION:
  328.             case WAN_MAKE_INVISIBLE:
  329.                 if(!oep) {        /* Eric Backus */
  330.                     type = DUST;
  331.                     break;
  332.                 }
  333.                 del_engr(oep);
  334.                 pline("The engraving on the floor vanishes!");
  335.                 return(1);
  336.                 /* break; */
  337.             case WAN_TELEPORTATION:
  338.                 if(!oep)
  339.                     type = DUST;
  340.                 else  {
  341.                     register int tx,ty;
  342.  
  343.                     do  {
  344.                         tx = rn1(COLNO-3,2);
  345.                         ty = rn2(ROWNO);
  346.                     }  while(!goodpos(tx,ty,(struct permonst *)0));
  347.                     oep->engr_x = tx;
  348.                     oep->engr_y = ty;
  349.                     pline("The engraving on the floor vanishes!");
  350.                     return(1);
  351.                 }
  352.                 break;
  353.             default:
  354.                 type = DUST;
  355.             }
  356.         }
  357.         if (otmp->spe < 0 && type != POLY) {
  358. dust:
  359.             /* If POLY, polymorph the writing and _then_ become dust. */
  360.             pline("The %s %sturns to dust.",
  361.                xname(otmp), Blind ? "" : "glows violently, then ");
  362.     You("are not going to get anywhere writing in the dust with your dust...");
  363.             useup(otmp);
  364.             return(1);
  365.         }
  366.         if(type == DUST)
  367.             You("write in the dust with %s.",
  368.                doname(otmp));
  369.  
  370.     } else {
  371.         if((otmp->otyp >= DAGGER && otmp->otyp <= AXE) ||
  372. #ifdef WORM
  373.            otmp->otyp == CRYSKNIFE ||
  374. #endif
  375.            is_sword(otmp)) {
  376.             type = ENGRAVE;
  377.  
  378.             if((int)otmp->spe <= -3) {
  379.                 Your("%s too dull for engraving.",
  380.                     aobjnam(otmp, "are"));
  381.                 type = DUST;
  382.                 /* following messaged added 10/20/86 - GAN */
  383.                 You("write in the dust with %s.",
  384.                    doname(otmp));
  385.             }  else
  386.                 You("engrave with %s.", doname(otmp));
  387.         } else if(otmp->otyp == MAGIC_MARKER)  {
  388.             if(otmp->spe <= 0)  {
  389.                 Your("marker is dried out.");
  390.                 You("write in the dust with the marker.");
  391.                 type = DUST;
  392.             }  else  {
  393.                 You("write with %s.", doname(otmp));
  394.                 type = MARK;
  395.             }
  396.         }  else  {
  397.             You("write in the dust with %s.",
  398.                doname(otmp));
  399.             type = DUST;
  400.         }
  401.     }
  402.  
  403.     if(type != POLY && oep && oep->engr_type == DUST){
  404.           You("wipe out the message that was written here.");
  405.           del_engr(oep);
  406.           oep = 0;
  407.     }
  408.     if(oep) {
  409.         You("cannot wipe out the message that is %s in the rock.",
  410.           (oep->engr_type == BURN) ? "burned" :
  411.           (oep->engr_type == ENGRAVE) ? "engraved" : "scribbled");
  412.           return(1);
  413.     }
  414.     if(type == POLY)  {
  415.         polytype = rnd(4);
  416.         Strcpy(buf,random_engr[rn2(SIZE(random_engr))]);
  417.         switch(polytype){
  418.         case DUST:
  419.             pline("\"%s\" is now written on the ground.",buf);
  420.             break;
  421.         case ENGRAVE:
  422.             pline("\"%s\" is now engraved in the rock.",buf);
  423.             break;
  424.         case BURN:
  425.             pline("\"%s\" is now burned in the rock.",buf);
  426.             break;
  427.         case MARK:
  428.             pline("\"%s\" is now scribbled on the rock.",buf);
  429.             break;
  430.         default:
  431.             impossible("\"%s\" is now written in a very strange way.",
  432.                buf);
  433.         }
  434.     }  else  {
  435.         pline("What do you want to %s on the floor here? ",
  436.           (type == ENGRAVE) ? "engrave" : (type == BURN) ? "burn" : "write");
  437.         getlin(buf);
  438.         clrlin();
  439.     }
  440.     spct = 0;
  441.     sp = buf;
  442.     while(*sp == ' ') spct++, sp++;
  443.     len = strlen(sp);
  444.     if(!len || *buf == '\033') {
  445.         /* changed by GAN 11/01/86 to not recharge wand */
  446.         return(1);
  447.     }
  448.     if(otmp->otyp == WAN_FIRE) {
  449.         if (!Blind) pline("Flames fly from the wand.");
  450.         else You("feel the wand heat up.");
  451.     } else if(otmp->otyp == WAN_LIGHTNING) {
  452.         if (!Blind) {
  453.             pline("Lightning arcs from the wand.");
  454.             You("are blinded by the flash!");
  455.             make_blinded((long)rnd(50),FALSE);
  456.         } else You("hear crackling!");
  457.     } else if(otmp->otyp == WAN_DIGGING) {
  458.         if (!Blind) pline("Gravel flies up from the floor.");
  459.         else You("hear drilling!");
  460.       }
  461.         /* kludge by stewr 870708 */
  462.     for (sptmp = sp, tmp=0; !(tmp == len); sptmp++,tmp++) {
  463.         if (((type == DUST) && !rn2(25))
  464.              || (Blind && !rn2(12))
  465.              || (Confusion && !rn2(3))) {
  466.              *sptmp = '!' + rn2(93); /* ASCII-code only */
  467.                }
  468.           }
  469.  
  470.     switch(type) {
  471.     case DUST:
  472.     case BURN:
  473.         if(len > 15) {
  474.             multi = -(len/10);
  475.             nomovemsg = "You finish writing.";
  476.         }
  477.         break;
  478.     case ENGRAVE:
  479.     case MARK:
  480.         {    int len2;
  481.  
  482.             if(type == ENGRAVE)
  483.                 len2 = (otmp->spe + 3) * 2 + 1;
  484.             else
  485.                 len2 = (otmp->spe) * 2;
  486.             nomovemsg = "You finish writing.";
  487.             if(type != MARK)
  488.             nomovemsg = "You finish engraving.";
  489.             if(otmp->olet != WAND_SYM && (otmp->otyp != ATHAME
  490.                     || otmp->cursed))  {
  491.                 if(otmp->olet == WEAPON_SYM)
  492.                     Your("%s dull.",
  493.                            aobjnam(otmp, "get"));
  494.                 if(len2 < len) {
  495.                     len = len2;
  496.                     sp[len] = 0;
  497.                     if(type == ENGRAVE)  {
  498.                         otmp->spe = -3;
  499.                     }  else  {
  500.                         Your("marker dries out!");
  501.                         otmp->spe = 0;
  502.                     }
  503.                     /* next line added by GAN 10/20/86 */
  504.                     You("only write \"%s\".", sp);
  505.                     nomovemsg = "You cannot write more.";
  506.                 } else
  507.                     otmp->spe -= len >> 1;
  508.                 if(type == MARK)
  509.                     multi = -(len/10);
  510.                 else
  511.                     multi = -len;
  512.             }  else
  513.                 multi = -(len/10);
  514.             if (multi == 0)
  515.                 nomovemsg = (char *)0;
  516.         }
  517.         break;
  518.     case POLY:
  519.         type = polytype;
  520.         multi = 0;
  521.         break;
  522.     }
  523.     if(oep) len += strlen(oep->engr_txt) + spct;
  524.     ep = (struct engr *) alloc((unsigned)(sizeof(struct engr) + len + 1));
  525.     ep->nxt_engr = head_engr;
  526.     head_engr = ep;
  527.     ep->engr_x = u.ux;
  528.     ep->engr_y = u.uy;
  529.     sp = (char *)(ep + 1);    /* (char *)ep + sizeof(struct engr) */
  530.     ep->engr_txt = sp;
  531.     if(oep) {
  532.         Strcpy(sp, oep->engr_txt);
  533.         Strcat(sp, buf);
  534.         del_engr(oep);
  535.     } else
  536.         Strcpy(sp, buf);
  537.     ep->engr_lth = len+1;
  538.     ep->engr_type = type;
  539.     ep->engr_time = moves-multi;
  540.  
  541.     /* kludge to protect pline against excessively long texts */
  542.     if(len > BUFSZ-20) sp[BUFSZ-20] = 0;
  543.  
  544.     /* cute messages for odd wands */
  545.     switch(otmp->otyp)  {
  546.     case WAN_SLOW_MONSTER:
  547.         pline("The bugs on the ground slow down!");
  548.         break;
  549.     case WAN_SPEED_MONSTER:
  550.         pline("The bugs on the ground speed up!");
  551.         break;
  552.     case WAN_MAGIC_MISSILE:
  553.         pline("The ground is riddled by bullet holes!");
  554.         break;
  555.     case WAN_SLEEP:
  556.     case WAN_DEATH:    /* can't tell sleep from death - Eric Backus */
  557.         pline("The bugs on the ground stop moving!");
  558.         break;
  559.     case WAN_COLD:
  560.         pline("A few ice cubes drop from your %s.",xname(otmp));
  561.         break;
  562.     case WAN_STRIKING:
  563.         pline("The %s unsuccessfully fights your attempt to write!",xname(otmp));
  564.     }
  565.     if (otmp->otyp == WAN_POLYMORPH && otmp->spe < 0) goto dust;
  566.     return(1);
  567. }
  568.  
  569. void
  570. save_engravings(fd) int fd; {
  571. register struct engr *ep = head_engr;
  572. register struct engr *ep2;
  573. #ifdef __GNULINT__
  574. static long nulls[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  575. #endif
  576.     while(ep) {
  577.         ep2 = ep->nxt_engr;
  578.         if(ep->engr_lth && ep->engr_txt[0]){
  579.         bwrite(fd, (genericptr_t)&(ep->engr_lth), sizeof(ep->engr_lth));
  580.         bwrite(fd, (genericptr_t)ep, sizeof(struct engr) + ep->engr_lth);
  581.         }
  582. #if defined(DGK)
  583.         if (!count_only)
  584. #endif
  585.         free((genericptr_t) ep);
  586.         ep = ep2;
  587.     }
  588.  
  589. #ifdef __GNULINT__
  590.     bwrite(fd, (genericptr_t)nulls, sizeof(unsigned));
  591. #else
  592.     bwrite(fd, (genericptr_t)nul, sizeof(unsigned));
  593. #endif
  594.  
  595. #if defined(DGK)
  596.     if (!count_only)
  597. #endif
  598.         head_engr = 0;
  599. }
  600.  
  601. void
  602. rest_engravings(fd) int fd; {
  603. register struct engr *ep;
  604. unsigned lth;
  605.     head_engr = 0;
  606.     while(1) {
  607.         mread(fd, (genericptr_t) <h, sizeof(unsigned));
  608.         if(lth == 0) return;
  609.         ep = (struct engr *) alloc(sizeof(struct engr) + lth);
  610.         mread(fd, (genericptr_t) ep, sizeof(struct engr) + lth);
  611.         ep->nxt_engr = head_engr;
  612.         ep->engr_txt = (char *) (ep + 1);    /* Andreas Bormann */
  613.         head_engr = ep;
  614.     }
  615. }
  616.  
  617. STATIC_OVL void
  618. del_engr(ep) register struct engr *ep; {
  619. register struct engr *ept;
  620.     if(ep == head_engr)
  621.         head_engr = ep->nxt_engr;
  622.     else {
  623.         for(ept = head_engr; ept; ept = ept->nxt_engr) {
  624.             if(ept->nxt_engr == ep) {
  625.                 ept->nxt_engr = ep->nxt_engr;
  626.                 goto fnd;
  627.             }
  628.         }
  629.         impossible("Error in del_engr?");
  630.         return;
  631.     fnd:    ;
  632.     }
  633.     free((genericptr_t) ep);
  634. }
  635.  
  636. #endif /* OVLB */
  637.